﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;

namespace Itasa.API
{
    internal static class ITASA_API
    {

        static readonly private String API_KEY = "436e566f3d09b217cf687fa5bad5effc";

        #region Funzioni per creare richieste secondo le API di itasa
        /*
         * Richiedere le news:
         * https://api.italiansubs.net/api/rest/news?page=<PAGE=1>
         */
        static private string newsRequest()
        {
            return "https://api.italiansubs.net/api/rest/news?apikey=" + API_KEY;
        }
        static private string newsRequest(int page)
        {
            return "https://api.italiansubs.net/api/rest/news?page=" + page + "&apikey=" + API_KEY;
        }

        /*
         * Richiedere una singola news:
         * https://api.italiansubs.net/api/rest/news/<NEWS_ID>
         */
        static private string singleNewsRequest(String newsid)
        {
            return "https://api.italiansubs.net/api/rest/news/" + newsid + "?apikey=" + API_KEY;
        }

        /*
         * Cercare una news:
         * https://api.italiansubs.net/api/rest/news/search?q=<Query>&page=<PAGE=1>
         */
        static private string newsSearchRequest(String query)
        {
            return "https://api.italiansubs.net/api/rest/news/search?q=" + query + "&apikey=" + API_KEY;
        }
        static private string newsSearchRequest(String query, int page)
        {
            return "https://api.italiansubs.net/api/rest/news/search?q=" + query + "&page=" + page + "&apikey=" + API_KEY;
        }

        /*
         * Richiedere gli show (viene stampata l'intera lista):
         * https://api.italiansubs.net/api/rest/shows?
         */
        static private string showsRequest()
        {
            return "https://api.italiansubs.net/api/rest/shows?apikey=" + API_KEY;
        }

        /*
         * Richiedere un singolo show:
         * https://api.italiansubs.net/api/rest/shows/<SHOW_ID>?
         */
        static private string showRequest(String showid)
        {
            return "https://api.italiansubs.net/api/rest/shows/" + showid + "?apikey=" + API_KEY;
        }

        /*
         * Immagine della cartella dello show (viene fatto un redirect all'URL dell'immagine; potrebbe non esistere):
         * https://api.italiansubs.net/api/rest/shows/<SHOW_ID>/folderThumb?
         */
        static private string showImageRequest(String showid)
        {
            return "https://api.italiansubs.net/api/rest/shows/" + showid + "/folderThumb?apikey=" + API_KEY;
        }

        /*
         * Cercare uno show:
         * https://api.italiansubs.net/api/rest/shows/search?q=<Query>&page=<PAGE=1>
         */
        static private string showSearchRequest(String query)
        {
            return "https://api.italiansubs.net/api/rest/shows/search?q=" + query + "&apikey=" + API_KEY;
        }
        static private string showSearchRequest(String query, int page)
        {
            return "https://api.italiansubs.net/api/rest/shows/search?q=" + query + "&page=" + page + "&apikey=" + API_KEY;
        }

        ///<summary>
        ///Richiedere i sottotitoli di uno show
        ///</summary>
        static private string subsRequest(String showid)
        {
            return "https://api.italiansubs.net/api/rest/subtitles?show_id=" + showid + "&apikey=" + API_KEY;
        }
        static private string subsRequest(String showid, int page)
        {
            return "https://api.italiansubs.net/api/rest/subtitles?show_id=" + showid + "&page=" + page + "&apikey=" + API_KEY;
        }
        static private string subsRequest(String showid, String version)
        {
            return "https://api.italiansubs.net/api/rest/subtitles?show_id=" + showid + "&version=" + version + "&apikey=" + API_KEY;
        }
        static private string subsRequest(String showid, String version, int page)
        {
            return "https://api.italiansubs.net/api/rest/subtitles?show_id=" + showid + "&version=" + version + "&page=" + page + "&apikey=" + API_KEY;
        }

        /*
         * Richiedere un sottotitolo:
         * https://api.italiansubs.net/api/rest/subtitles/<SUBTITLE_ID>?
         */
        static private string subRequest(String subtitleID)
        {
            return "https://api.italiansubs.net/api/rest/subtitles/" + subtitleID + "?apikey=" + API_KEY;
        }

        /*
         * Cercare un sottotitolo:
         * https://api.italiansubs.net/api/rest/subtitles/search?q=<QUERY>&show_id=<SHOW_ID>&version=<VERSION=null>&page=<PAGE=1>
         */
        static private string subSearchRequest(String query, String showid)
        {
            return "https://api.italiansubs.net/api/rest/subtitles/search?q=" + query + "&show_id=" + showid + "&apikey=" + API_KEY;
        }
        static private string subSearchRequest(String query, String showid, int page)
        {
            return "https://api.italiansubs.net/api/rest/subtitles/search?q=" + query + "&show_id=" + showid + "&page=" + page + "&apikey=" + API_KEY;
        }
        static private string subSearchRequest(String query, String showid, String version)
        {
            return "https://api.italiansubs.net/api/rest/subtitles/search?q=" + query + "&show_id=" + showid + "&version=" + version + "&apikey=" + API_KEY;
        }
        static private string subSearchRequest(String query, String showid, String version, int page)
        {
            return "https://api.italiansubs.net/api/rest/subtitles/search?q=" + query + "&show_id=" + showid + "&version=" + version + "&page=" + page + "&apikey=" + API_KEY;
        }

        /*
         * Login:
         * https://api.italiansubs.net/api/rest/users/login?username=<USERNAME>&password=<PASSWORD>
         */
        static private string loginRequest(String username, String password)
        {
            return "https://api.italiansubs.net/api/rest/users/login?username=" + username + "&password=" + password + "&apikey=" + API_KEY;
        }


        /*
         * Dati dell'utente proprietario dell'authcode:
         * https://api.italiansubs.net/api/rest/users/
         */
        static private string userDataRequest(ITASA_user user)
        {
            return "https://api.italiansubs.net/api/rest/users/?authcode=" + user.AuthCode + "&apikey=" + API_KEY;
        }

        /*
         * Profilo di un utente:
         * https://api.italiansubs.net/api/rest/users/<USER_ID>?
         */
        static private string userProfileRequest(ITASA_user user)
        {
            return "https://api.italiansubs.net/api/rest/users/" + user.ID + "?authcode=" + user.AuthCode + "&apikey=" + API_KEY;
        }

        /*
         * PM ricevuti (fase BETA, è solo un esempio, potrebbe quasi sicuramente cambiare):
         * https://api.italiansubs.net/api/rest/pms/inbox
         */
        static private string userPmInRequest(ITASA_user user)
        {
            return "https://api.italiansubs.net/api/rest/pms/inbox?authcode=" + user.AuthCode + "&apikey=" + API_KEY;
        }

        /*
         * PM inviati (fase BETA, è solo un esempio, potrebbe quasi sicuramente cambiare):
         * https://api.italiansubs.net/api/rest/pms/outbox
         */
        static private string userPmOutRequest(ITASA_user user)
        {
            return "https://api.italiansubs.net/api/rest/pms/outbox?authcode=" + user.AuthCode + "&apikey=" + API_KEY;
        }

        /*
         * Serie preferite, insieme alla versione dei sottotitoli preferita (la versione è da correggere):
         * https://api.italiansubs.net/api/rest/myitasa/shows
         */
        static private string userShowRequest(ITASA_user user)
        {
            return "https://api.italiansubs.net/api/rest/myitasa/shows?authcode=" + user.AuthCode + "&apikey=" + API_KEY;
        }

        /*
         * Gli ultimi sottotitoli delle serie preferite:
         * https://api.italiansubs.net/api/rest/myitasa/lastsubtitles?page=<PAGE=1>
         */
        static private string userSubsRequest(ITASA_user user)
        {
            return "https://api.italiansubs.net/api/rest/myitasa/lastsubtitles?authcode=" + user.AuthCode + "&apikey=" + API_KEY;
        }
        static private string userSubsRequest(ITASA_user user, int page)
        {
            return "https://api.italiansubs.net/api/rest/myitasa/lastsubtitles?page=" + page + "&authcode=" + user.AuthCode + "&apikey=" + API_KEY;
        }

        /*
         * I prossimi episodi delle serie preferite:
         * https://api.italiansubs.net/api/rest/myitasa/nextepisodes?page=<PAGE=1>
         */
        static private string userNextRequest(ITASA_user user)
        {
            return "https://api.italiansubs.net/api/rest/myitasa/nextepisodes?authcode=" + user.AuthCode + "&apikey=" + API_KEY;
        }
        static private string userNextRequest(ITASA_user user, int page)
        {
            return "https://api.italiansubs.net/api/rest/myitasa/nextepisodes?page=" + page + "&authcode=" + user.AuthCode + "&apikey=" + API_KEY;
        }
        #endregion

        static internal ITASA_user login(String username, String password)
        {
            WebClient WC = new WebClient();
            String xml = WC.DownloadString(loginRequest(username, password));
            XmlDocument xd = new XmlDocument();
            xd.LoadXml(xml);
            return ITASA_user.getInstance(xd);
        }

        static internal ITASA_user userProfile(ITASA_user user)
        {
            WebClient WC = new WebClient();
            String xml = WC.DownloadString(userProfileRequest(user));
            XmlDocument xd = new XmlDocument();
            xd.LoadXml(xml);
            return ITASA_user.getInstance(xd);
        }

        static internal ITASA_user userData(ITASA_user user)
        {
            WebClient WC = new WebClient();
            String xml = WC.DownloadString(userDataRequest(user));
            XmlDocument xd = new XmlDocument();
            xd.LoadXml(xml);
            return ITASA_user.getInstance(xd);
        }

        static private bool error(XmlNode root)
        {
            return !root.ChildNodes[0].HasChildNodes && root.ChildNodes[1].InnerText == "fail";
        }
        static private void handleError(XmlNode root)
        {
            XmlNode error = root.ChildNodes[2];
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("Error Code {0}: {1}", error.FirstChild.InnerText, error.LastChild.InnerText);
            Params.writeLog(sb.ToString());
        }

        static internal List<Episode> favNextEpisodes(ITASA_user user)
        {
            WebClient WC = new WebClient();
            int totpage = 1;
            int currentpage = 1;
            int total_items = int.MinValue;
            String next;
            if (user != null && user.HasMyItasa)
            {
                List<Episode> li = new List<Episode>();
                while (currentpage <= totpage)
                {
                    String xml = WC.DownloadString(userNextRequest(user, currentpage));
                    XmlDocument xd = new XmlDocument();
                    xd.LoadXml(xml);
                    XmlNode root = xd.DocumentElement;
                    if (root.Name == "root")
                    {
                        if (error(root))
                        {
                            handleError(root);
                            return null;
                        }
                        else
                        {
                            XmlNode data = root.FirstChild;
                            {
                                XmlNode items = data.ChildNodes[0];
                                currentpage = int.Parse(data.ChildNodes[1].InnerText);
                                totpage = int.Parse(data.ChildNodes[2].InnerText);
                                total_items = int.Parse(data.ChildNodes[3].InnerText);
                                next = data.ChildNodes[4].InnerText;
                                {
                                    foreach (XmlNode item in items.ChildNodes)
                                    {
                                        li.Add(new Episode(item));
                                    }
                                }
                            }
                        }
                    }
                    currentpage++;
                }
                return li;
            }
            return null;
        }

        static internal List<Sub> favLastSubs(ITASA_user user)
        {
            WebClient WC = new WebClient();
            int totpage = 1;
            int currentpage = 1;
            int total_items = int.MinValue;
            String next;
            if (user != null && user.HasMyItasa)
            {
                List<Sub> li = new List<Sub>();
                while (currentpage <= totpage)
                {
                    String xml = WC.DownloadString(userSubsRequest(user, currentpage));
                    XmlDocument xd = new XmlDocument();
                    xd.LoadXml(xml);
                    XmlNode root = xd.DocumentElement;
                    if (root.Name == "root")
                    {
                        if (error(root))
                        {
                            handleError(root);
                            return null;
                        }
                        else
                        {
                            XmlNode data = root.FirstChild;
                            {
                                XmlNode items = data.ChildNodes[0];
                                currentpage = int.Parse(data.ChildNodes[1].InnerText);
                                totpage = int.Parse(data.ChildNodes[2].InnerText);
                                total_items = int.Parse(data.ChildNodes[3].InnerText);
                                next = data.ChildNodes[4].InnerText;
                                {
                                    foreach (XmlNode item in items.ChildNodes)
                                    {
                                        Sub s = new Sub(item);
                                        if (li.Contains(s))
                                        {
                                            li[li.IndexOf(s)].AddDownloadDate(s.DownloadDate);
                                        }
                                        else li.Add(s);
                                    }
                                }
                            }
                        }
                    }
                    currentpage++;
                }
                return li;
            }
            return null;
        }

        static internal int favLastSubs(List<Sub> li, ITASA_user user, int page)
        {
            if (user != null && user.HasMyItasa && li != null)
            {
                int totpage = page;
                WebClient WC = new WebClient();
                String xml = WC.DownloadString(userSubsRequest(user, page));
                XmlDocument xd = new XmlDocument();
                xd.LoadXml(xml);
                XmlNode root = xd.DocumentElement;
                if (root.Name == "root")
                {
                    if (error(root))
                    {
                        handleError(root);
                        return -1;
                    }
                    else
                    {
                        XmlNode data = root.FirstChild;
                        {
                            XmlNode items = data.ChildNodes[0];
                            totpage = int.Parse(data.ChildNodes[2].InnerText);
                            {
                                foreach (XmlNode item in items.ChildNodes)
                                {
                                    Sub s = new Sub(item);
                                    if (li.Contains(s))
                                    {
                                        li[li.IndexOf(s)].AddDownloadDate(s.DownloadDate);
                                    }
                                    else li.Add(s);
                                }
                            }
                        }
                    }
                }
                return totpage - page;
            }
            return -1;
        }

        static internal List<Show> favShows(ITASA_user user)
        {
            WebClient WC = new WebClient();
            if (user != null && user.HasMyItasa)
            {
                List<Show> li = new List<Show>();
                String xml = WC.DownloadString(userShowRequest(user));
                XmlDocument xd = new XmlDocument();
                xd.LoadXml(xml);
                XmlNode root = xd.DocumentElement;
                if (root.Name == "root")
                {
                    if (error(root))
                    {
                        handleError(root);
                        return null;
                    }
                    else
                    {
                        XmlNode data = root.FirstChild;
                        {
                            XmlNode items = data.ChildNodes[0];
                            {
                                foreach (XmlNode item in items.ChildNodes)
                                {
                                    String ID = null;
                                    List<Version> Versions = null;
                                    foreach (XmlNode sd in item.ChildNodes)
                                    {
                                        if (sd.InnerText != null)
                                        {
                                            if (sd.Name == "id") ID = sd.InnerText;
                                            if (sd.Name == "versions")
                                            {
                                                Versions = new List<Version>();
                                                foreach (XmlNode vd in sd.ChildNodes)
                                                {
                                                    if (vd.InnerText != null)
                                                    {
                                                        if (vd.Name == "version") Versions.Add(new Version(vd.InnerText));
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    if (ID != null)
                                    {
                                        li.Add(parseShow(ID, Versions));
                                        //li.Add(new Show(item));
                                    }
                                }
                            }
                        }
                    }
                }
                return li;
            }
            return null;
        }

        static private Show parseShow(String ID, List<Version> Versions)
        {
            WebClient WC = new WebClient();
            String xml = WC.DownloadString(showRequest(ID));
            XmlDocument xd = new XmlDocument();
            xd.LoadXml(xml);
            XmlNode root = xd.DocumentElement;
            if (root.Name == "root")
            {
                if (error(root))
                {
                    handleError(root);
                    return null;
                }
                else
                {
                    XmlNode data = root.FirstChild;
                    {
                        XmlNode item = data.ChildNodes[0];
                        {
                            Show s = new Show(item, Versions);
                            return s;
                        }
                    }
                }
            }

            return null;
        }

        static private List<Episode> parseEpisodes(String ID)
        {
            WebClient WC = new WebClient();
            String xml = WC.DownloadString(showRequest(ID));
            XmlDocument xd = new XmlDocument();
            xd.LoadXml(xml);
            XmlNode root = xd.DocumentElement;
            if (root.Name == "root")
            {
                if (error(root))
                {
                    handleError(root);
                    return null;
                }
                else
                {
                    XmlNode data = root.FirstChild;
                    {
                        XmlNode item = data.ChildNodes[0];
                        {
                            long id = 0;
                            String name = null;
                            String[] Last = new String[3];
                            String[] Next = new String[3];
                            foreach (XmlNode sd in item.ChildNodes)
                            {
                                if (sd.InnerText != null)
                                {
                                    if (sd.Name == "id") id = long.Parse(sd.InnerText);
                                    if (sd.Name == "name") name = sd.InnerText;
                                    if (sd.Name == "lastep_num") Last[0] = sd.InnerText;
                                    if (sd.Name == "lastep_title") Last[1] = sd.InnerText;
                                    if (sd.Name == "lastep_date") Last[2] = sd.InnerText;
                                    if (sd.Name == "nextep_num") Next[0] = sd.InnerText;
                                    if (sd.Name == "nextep_title") Next[1] = sd.InnerText;
                                    if (sd.Name == "nextep_date") Next[2] = sd.InnerText;
                                }
                            }
                            List<Episode> le = new List<Episode>();
                            le.Add(new Episode(name, id, Last));
                            le.Add(new Episode(name, id, Next));
                            return le;
                        }
                    }
                }
            }
            return null;
        }

        static internal string i_subRequest(String subtitleID)
        {
            return subRequest(subtitleID);
        }

        static internal string i_showRequest(String showID)
        {
            return showRequest(showID);
        }

        static internal SubInfo subInfo(String subID)
        {
            WebClient WC = new WebClient();
            int tries = 0;
            String xml = null;
            bool ok = false;
            while (tries < 3 && !ok)
            {
                try
                {
                    xml = WC.DownloadString(subRequest(subID));
                    ok = true;
                }
                catch (WebException)
                {
                    tries++;
                }
            }
            if (!ok)
            {
                Params.writeLog("Impossibile recuperare informazioni sul sottotitolo " + subID);
                return null;
            }
            XmlDocument xd = new XmlDocument();
            xd.LoadXml(xml);
            XmlNode root = xd.DocumentElement;
            if (root.Name == "root")
            {
                if (error(root))
                {
                    handleError(root);
                    return null;
                }
                else
                {
                    XmlNode data = root.FirstChild;
                    {
                        XmlNode item = data.FirstChild;
                        return new SubInfo(item);
                    }
                }
            }
            return null;
        }

    }
}

//http://www.italiansubs.net/index.php?option=com_myitasa&Itemid=22&mode=addserie&serie=408&redirect=archive
//http://www.italiansubs.net/index.php?option=com_myitasa&Itemid=22&mode=remserie&serie=408&start=